package com.ruoyi.quality.service.impl;

import cn.hutool.core.bean.BeanUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.ruoyi.common.DateRangeUtil.DateRangeUtil;
import com.ruoyi.common.core.domain.PageQuery;
import com.ruoyi.common.core.page.TableDataInfo;
import com.ruoyi.common.utils.StringUtils;
import com.ruoyi.quality.domain.QualityAnalysis;
import com.ruoyi.quality.domain.bo.QualityAnalysisBo;
import com.ruoyi.quality.domain.bo.QualityPhysicalDefectBo;
import com.ruoyi.quality.domain.bo.QualityPhysicalReportBo;
import com.ruoyi.quality.domain.vo.QualityAnalysisVo;
import com.ruoyi.quality.domain.vo.QualityPhysicalDefectVo;
import com.ruoyi.quality.domain.vo.QualityPhysicalReportVo;
import com.ruoyi.quality.mapper.QualityAnalysisMapper;
import com.ruoyi.quality.service.IQualityAnalysisService;
import com.ruoyi.quality.service.IQualityPhysicalDefectService;
import com.ruoyi.quality.service.IQualityPhysicalReportService;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 实物质量分析Service业务层处理
 *
 * @author ruoyi
 * @date 2023-08-07
 */
@RequiredArgsConstructor
@Service
public class QualityAnalysisServiceImpl implements IQualityAnalysisService {

    private final QualityAnalysisMapper baseMapper;
    private final IQualityPhysicalReportService reportService;
    private final IQualityPhysicalDefectService defectService;

    /**
     * 查询实物质量分析
     */
    @Override
    public QualityAnalysisVo queryById(Long id){
        return baseMapper.selectVoById(id);
    }

    /**
     * 查询实物质量分析列表
     */
    @Override
    public TableDataInfo<QualityAnalysisVo> queryPageList(QualityAnalysisBo bo, PageQuery pageQuery) {
        LambdaQueryWrapper<QualityAnalysis> lqw = buildQueryWrapper(bo);
        Page<QualityAnalysisVo> result = baseMapper.selectVoPage(pageQuery.build(), lqw);
        return TableDataInfo.build(result);
    }

    /**
     * 查询实物质量分析列表
     */
    @Override
    public List<QualityAnalysisVo> queryList(QualityAnalysisBo bo) {
        LambdaQueryWrapper<QualityAnalysis> lqw = buildQueryWrapper(bo);
        return baseMapper.selectVoList(lqw);
    }

    private LambdaQueryWrapper<QualityAnalysis> buildQueryWrapper(QualityAnalysisBo bo) {
        Map<String, Object> params = bo.getParams();
        LambdaQueryWrapper<QualityAnalysis> lqw = Wrappers.lambdaQuery();
        lqw.eq(StringUtils.isNotBlank(bo.getDeptAbbreviation()), QualityAnalysis::getDeptAbbreviation, bo.getDeptAbbreviation());
        lqw.eq(StringUtils.isNotBlank(bo.getTitle()), QualityAnalysis::getTitle, bo.getTitle());
        lqw.eq(bo.getDeptCommentary() != null, QualityAnalysis::getDeptCommentary, bo.getDeptCommentary());
        lqw.eq(bo.getGroupCommentary() != null, QualityAnalysis::getGroupCommentary, bo.getGroupCommentary());
        lqw.eq(bo.getAnalysisMonth() != null, QualityAnalysis::getAnalysisMonth, bo.getAnalysisMonth());
        lqw.eq(bo.getTechnologyReportNumber() != null, QualityAnalysis::getTechnologyReportNumber, bo.getTechnologyReportNumber());
        lqw.eq(bo.getTechnologyDefectNumber() != null, QualityAnalysis::getTechnologyDefectNumber, bo.getTechnologyDefectNumber());
        lqw.eq(bo.getTechnologyDefectFine() != null, QualityAnalysis::getTechnologyDefectFine, bo.getTechnologyDefectFine());
        lqw.eq(bo.getPhysicalReportNumber() != null, QualityAnalysis::getPhysicalReportNumber, bo.getPhysicalReportNumber());
        lqw.eq(bo.getPhysicalDefectNumber() != null, QualityAnalysis::getPhysicalDefectNumber, bo.getPhysicalDefectNumber());
        lqw.eq(bo.getPhysicalDefectFine() != null, QualityAnalysis::getPhysicalDefectFine, bo.getPhysicalDefectFine());
        lqw.eq(bo.getDefectTotal() != null, QualityAnalysis::getDefectTotal, bo.getDefectTotal());
        lqw.eq(bo.getListNumber() != null, QualityAnalysis::getListNumber, bo.getListNumber());
        lqw.eq(bo.getListDefect() != null, QualityAnalysis::getListDefect, bo.getListDefect());
        lqw.orderByDesc(QualityAnalysis::getAnalysisDate);
        lqw.between(params.get("beginAnalysisDate") != null && params.get("endAnalysisDate") != null,
            QualityAnalysis::getAnalysisDate ,params.get("beginAnalysisDate"), params.get("endAnalysisDate"));
        return lqw;
    }

    /**
     * 新增实物质量分析
     */
    @Override
    public Boolean insertByBo(QualityAnalysisBo bo) {
        QualityAnalysis add = BeanUtil.toBean(bo, QualityAnalysis.class);
        extracted(bo, add);
        validEntityBeforeSave(add);
        boolean flag = baseMapper.insert(add) > 0;
        if (flag) {
            bo.setId(add.getId());
        }
        return flag;
    }

    /**
     * 修改实物质量分析
     */
    @Override
    public Boolean updateByBo(QualityAnalysisBo bo) {
        QualityAnalysis update = BeanUtil.toBean(bo, QualityAnalysis.class);
        update.setTechnologyReportNumber(0);
        update.setTechnologyDefectNumber(0);
        update.setTechnologyDefectFine(0);
        update.setPhysicalReportNumber(0);
        update.setPhysicalDefectNumber(0);
        update.setPhysicalDefectFine(0);
        extracted(bo, update);
        validEntityBeforeSave(update);
        return baseMapper.updateById(update) > 0;
    }

    /**
     * 保存前的数据校验
     */
    private void validEntityBeforeSave(QualityAnalysis entity){
        //TODO 做一些数据校验,如唯一约束
    }

    /**
     * 批量删除实物质量分析
     */
    @Override
    public Boolean deleteWithValidByIds(Collection<Long> ids, Boolean isValid) {
        if(isValid){
            //TODO 做一些业务上的校验,判断是否需要校验
        }
        return baseMapper.deleteBatchIds(ids) > 0;
    }

    /**
     * 查询当月分析报告列表
     */
    @Override
    public List<Object> getAnalysisReportList(QualityPhysicalReportBo bo){
        List<Object> result = new ArrayList<>();
        //获取问题列表
        List<QualityPhysicalDefectVo> defectVoList = new ArrayList<>();
        List<QualityPhysicalReportVo> reportVoList = reportService.queryList(bo);
        if (reportVoList != null && !reportVoList.isEmpty()){
            reportVoList.forEach(item->{
                Long reportId = item.getReportId();
                QualityPhysicalDefectBo defectBo = new QualityPhysicalDefectBo();
                defectBo.setReportId(reportId);
                List<QualityPhysicalDefectVo> defectVos = defectService.queryList(defectBo);
                if (!defectVos.isEmpty()){
                    item.setDefectList(defectVos);
                }
                defectVoList.addAll(defectVos);
            });

            //格式化问题列表
            List<Map<String, Object>> pieList = formatMaps(defectVoList);


            //重写比较器，降序排列
            pieList.sort((o1, o2) -> {
                Integer key1 = Integer.valueOf(o1.get("value").toString());
                Integer key2 = Integer.valueOf(o2.get("value").toString());
                return key2.compareTo(key1);
            });

            //问题总数
            int pieListSize = pieList.size();

            if (pieListSize!=0){
                List<Map<String, Object>> pieListTop8 = getTopMaps(pieList, Math.min(pieListSize, 8));
                Map<String,Object> top8Map = new HashMap<>(8);
                top8Map.put("pieList",pieListTop8);

                List<Map<String, Object>> pieListTop3 = getTopMaps(defectVoList, pieList, Math.min(pieListSize, 3));
                Map<String,Object> top3Map = new HashMap<>(8);
                top3Map.put("topList",pieListTop3);

                result.add(top8Map);
                result.add(top3Map);
            }
        }

        return result;
    }

    private static List<Map<String, Object>> formatMaps(List<QualityPhysicalDefectVo> defectVoList) {
        List<Map<String, Object>> result = new ArrayList<>();
        //根据工件名称和分类进行统计
        Map<String, List<QualityPhysicalDefectVo>> defectMap = defectVoList.stream().collect(Collectors.groupingBy(defect -> defect.getPartName() +"_"+ defect.getDefectClassification()));
        for (Map.Entry<String, List<QualityPhysicalDefectVo>> stringListEntry : defectMap.entrySet()) {
            Map<String, Object> newMap = new HashMap<>(8);
            String key = stringListEntry.getKey();
            List<QualityPhysicalDefectVo> physicalDefect = stringListEntry.getValue();
            int size = physicalDefect.size();

            if (key.isEmpty()){
                key = "";
            }
            newMap.put("name",key);
            newMap.put("value",size);
            result.add(newMap);
        }
        return result;
    }

    @Override
    public List<Map<String, Object>> getAllTop(int topNumber) {
        QualityPhysicalDefectBo bo = new QualityPhysicalDefectBo();
        List<QualityPhysicalDefectVo> defectVoList = defectService.queryList(bo);
        List<Map<String, Object>> mapList = formatMaps(defectVoList);
        int pieListSize = mapList.size();
        return getTopMaps(mapList, Math.min(pieListSize, topNumber));
    }

    @Override
    public List<Map<String, Object>> getTopPreview(Long[] ids) {
        List<Map<String, Object>> result = new ArrayList<>();
        // 假设getContentById方法用于从数据库或其他数据源中获取内容
        for (Long id : ids) {
            Map<String, Object> contentMap = getTopByAnasId(id);
            result.add(contentMap);
        }
        return result;
    }

    private Map<String, Object> getTopByAnasId(Long anasId) {
        QualityAnalysisVo vo = baseMapper.selectVoById(anasId);
        Map<String, Object> newMap = new HashMap<>(8);
        newMap.put("dept",vo.getDeptAbbreviation());
        newMap.put("date",vo.getAnalysisMonth());
        newMap.put("hasChildren","true");
        Map<String, Object>  dateRange = DateRangeUtil.getThisMonthRange(vo.getAnalysisMonth());
        QualityPhysicalReportBo reportBo = new QualityPhysicalReportBo();
        reportBo.setDeptAbbreviation(vo.getDeptAbbreviation());
        reportBo.setParams(dateRange);
        List<Object> topList = getAnalysisReportList(reportBo);
        Map<String, Object> topMap = (Map<String, Object>) topList.get(1);
        newMap.put("topList",topMap.get("topList") );
        return newMap;
    }

    private static List<Map<String, Object>> getTopMaps(List<Map<String, Object>> list, int topNumber) {
        List<Map<String, Object>> result = new ArrayList<>();
        for (int i = 0; i < topNumber; i++) {
            Map<String, Object> newMap1 = list.get(i);
            if (!newMap1.isEmpty()){
                result.add(newMap1);
            }
        }
        return result;
    }

    private static List<Map<String, Object>> getTopMaps(List<QualityPhysicalDefectVo> defectVoList, List<Map<String, Object>> list, int number) {
        List<Map<String, Object>> result = new ArrayList<>();
        for (int i = 0; i < number; i++) {
            Map<String, Object> newMap2 = new HashMap<>(8);
            Map<String, Object> newMap3 = list.get(i);
            if (!newMap3.isEmpty()){
                String name = newMap3.get("name").toString();
                int value = (int) newMap3.get("value");
                float newValue = (float)value/ defectVoList.size()*100;
                BigDecimal b = new BigDecimal(newValue);
                float f1 = b.setScale(1, RoundingMode.HALF_UP).floatValue();
                newMap2.put("name",name);
                newMap2.put("value",f1);
            }else {
                newMap2.put("name","");
                newMap2.put("value","");
            }
            result.add(newMap2);
        }
        return result;
    }

    /**
     * 获取质量通报分析数据
     */
    private void extracted(QualityAnalysisBo bo, QualityAnalysis analysis) {
        QualityPhysicalReportBo reportBo = new QualityPhysicalReportBo();
        reportBo.setParams(bo.getParams());
        reportBo.setDeptAbbreviation(bo.getDeptAbbreviation());

        List<QualityPhysicalReportVo> reportVoList = reportService.queryList(reportBo);
        //获取问题列表
        reportVoList.forEach(item->{
            Long reportId = item.getReportId();
            QualityPhysicalDefectBo defectBo = new QualityPhysicalDefectBo();
            defectBo.setReportId(reportId);
            List<QualityPhysicalDefectVo> defectVos = defectService.queryList(defectBo);
            item.setDefectList(defectVos);
        });

        //根据通报名称分组
        Map<String, List<QualityPhysicalReportVo>> reportMap = reportVoList.stream().collect(Collectors.groupingBy(QualityPhysicalReportVo::getReportName));

        //工艺执行通报
        List<QualityPhysicalReportVo> technologyReport = reportMap.get("1");
        List<QualityPhysicalDefectVo> technologyDefectVoList = new ArrayList<>();
        if (technologyReport != null && !technologyReport.isEmpty()) {
            technologyReport.forEach(item-> technologyDefectVoList.addAll(item.getDefectList()));
            int technologyDefectFineSum = technologyDefectVoList.stream().mapToInt(QualityPhysicalDefectVo::getDefectFine).sum();
            analysis.setTechnologyReportNumber(technologyReport.size());
            analysis.setTechnologyDefectNumber(technologyDefectVoList.size());
            analysis.setTechnologyDefectFine(technologyDefectFineSum);
        }

        //文明操作通报
        List<QualityPhysicalReportVo> physicalReport = reportMap.get("2");
        List<QualityPhysicalDefectVo> physicalDefectVoList = new ArrayList<>();
        if (physicalReport != null && !physicalReport.isEmpty()) {
            physicalReport.forEach(item-> physicalDefectVoList.addAll(item.getDefectList()));
            int physicalDefectFineSum = physicalDefectVoList.stream().mapToInt(QualityPhysicalDefectVo::getDefectFine).sum();
            analysis.setPhysicalReportNumber(physicalReport.size());
            analysis.setPhysicalDefectNumber(physicalDefectVoList.size());
            analysis.setPhysicalDefectFine(physicalDefectFineSum);
        }

        analysis.setDefectTotal(technologyDefectVoList.size()+ physicalDefectVoList.size());
        analysis.setListNumber(1);
        analysis.setListDefect(20);
    }

}
